//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
#if _MSC_VER > 1000
#pragma once
#endif

#ifndef __GHOST_PROCESS_H__
#define __GHOST_PROCESS_H__

#include <elasys_server.h>
#include <interlocked.h>
#include "ghost.h"
#include <aura.h>

class CGhostProcess: public Ghost
{
public:  // for Ghost Interface.
    UInt32 AddRef();
    UInt32 Release();

public:  // for GProcess interface.
    ECode Kill(
        /* [in] */ ExitCode exitCode);

    ECode GetStartInfo(
        /* [out] */ WStringBuf ** ppName,
        /* [out] */ WStringBuf ** ppArgs);

    ECode GetExitCode(
        /* [out] */ ExitCode * pExitCode);

    ECode GetStartTime(
        /* [out] */ SystemTime * pTime);

    ECode GetExitTime(
        /* [out] */ SystemTime * pTime);

    ECode WaitForExit(
        /* [in] */ Millisecond32 ms,
        /* [out] */ WaitResult * pResult);

    ECode IsAlive(
        /* [out] */ Boolean * pbAlive);

    ECode GetId(
        /* [out] */ ProcessId * pProcessId);

    ECode GetProcessorTimes(
        /* [out] */ Millisecond32 * pUserTime,
        /* [out] */ Millisecond32 * pPrivilegedTime);

    ECode DoAtExit(
        /* [in] */ ExitCode exitCode,
        /* [in] */ Millisecond32 userTime,
        /* [in] */ Millisecond32 privilegedTime);

    ECode DoAtExceptionalExit(
        /* [out] */ Boolean * pbAlive);

public:
    CGhostProcess();
    virtual ~CGhostProcess();

    ECode Initialize0(WString, WString);
    void  Initialize1(ProcessId, Aura_Handle);
    Boolean IsEqual(ProcessId pid) {return m_processId == pid; }

public:
    STATIC DLinkNode s_hashList[GHOST_HS_SLOTS];
    STATIC DLinkNode s_activeList;
    STATIC Int32     s_activeListState;
    STATIC PVoid     s_hLock;

    STATIC ECode S_Initialize();
    STATIC void  S_Destroy();

    STATIC ECode S_Create(
        /* [in] */ WString name,
        /* [in] */ WString args,
        /* [in] */ ProcessId processId);

    STATIC ECode S_Create(
        /* [in] */ ThreadPriorityRank priorityRank,
        /* [in] */ Int32 capacity,
        /* [in] */ WString name,
        /* [in] */ WString args,
        /* [out]*/ CGhostProcess ** ppGhost);

    STATIC ECode S_Find(
        /* [in] */ ProcessId processId,
        /* [out]*/ CGhostProcess ** ppGhost);

    STATIC void  S_DeleteFromActiveList(
        /* [in] */ CGhostProcess * pGhost);

    STATIC void  S_DeleteFromHashList(
        /* [in] */ CGhostProcess * pGhost);

public:
    DLinkNode  m_inList;

private:
    ProcessId  m_processId;
    Aura_Handle     m_hProcess;
    Boolean    m_bAlive;

    PVoid      m_hExitLock;

    SystemTime m_startTime;
    SystemTime m_exitTime;
    ExitCode   m_exitCode;

    Millisecond32 m_userTime;
    Millisecond32 m_privilegedTime;

    WStringBuf * m_pName;
    WStringBuf * m_pArgs;
    WStringBuf_<2> m_args;

    PVoid      m_hExitEvent;

private:
    Interlocked m_nRefs;
};

class CGhostProcessFactory: public GhostFactory
{
public:
    ECode CreateGhost(
        /* [out] */ Ghost ** ppGhost,
        /* [out] */ Boolean * pbExists);

    ECode GetGhost(
        /* [out] */ Ghost ** ppGhost);

    ECode DeleteGhost(
        /* [in] */ Ghost * pGhost) { _GHOST_UNUSED(); }

public:
    CGhostProcessFactory(ProcessId processId) : m_processId(processId){}

    CGhostProcessFactory(ThreadPriorityRank priorityRank,
                        Int32 capacity,
                        WString name,
                        WString args)
                      : m_priorityRank(priorityRank),
                        m_capacity(capacity),
                        m_name(name),
                        m_args(args) {}

private:
    ProcessId m_processId;

    ThreadPriorityRank m_priorityRank;
    Int32   m_capacity;
    WString m_name;
    WString m_args;
};

INLINE CGhostProcess::CGhostProcess()
        : m_processId(0),
          m_hProcess(NULL),
          m_bAlive(FALSE),
          m_hExitLock(NULL),
          m_userTime(0),
          m_privilegedTime(0),
          m_pName(NULL),
          m_pArgs(NULL),
          m_hExitEvent(NULL)
{
    DLinkNode::Initialize();
    m_inList.Initialize();
}

INLINE void CGhostProcess::Initialize1(
        /* [in] */ ProcessId processId,
        /* [in] */ Aura_Handle hProcess)
{
    m_processId = processId;
    m_hProcess  = hProcess;

    m_bAlive = TRUE;
    return ;
}

#endif  //__GHOST_PROCESS_H__
